#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
//    this->setWindowFlag(Qt::FramelessWindowHint);       //去边框

    //设置按钮不可按
    ui->selectPushButton->setEnabled(false);        //选择文件按钮不可按
    ui->sendPushButton->setEnabled(false);          //发送文件按钮不可按

    tcpServer = new QTcpServer(this);           //创建服务器对象
    tcpServer->listen(QHostAddress::Any,PORT);          //监听任意ip地址和端口号

    sendFileTimer = new QTimer(this);

    connect(tcpServer,&QTcpServer::newConnection,this,&Widget::newConnectionHandler);    //处理新连接

    connect(sendFileTimer,&QTimer::timeout,this,&Widget::sendFileTimeoutHandler);        //定时器结束处理
}

Widget::~Widget()
{
    delete ui;
}

//处理新连接
void Widget::newConnectionHandler()
{
    //建立Tcp连接
    tcpSocket = tcpServer->nextPendingConnection();     //取出下一个连接的套接字

    //获取ip地址和端口号
    QString ip = tcpSocket->peerAddress().toString();   //ip地址
    qint16 Port = tcpSocket->peerPort();                //端口号

    //显示ip地址和端口号
    ui->ipLineEdit->setText(ip);            //在ip输入框上显示
    ui->portLineEdit->setText(QString::number(Port));        //在Port输入框中显示

    QString connectTemp = QString("[%1:%2] 已连接").arg(ip).arg(Port);     //已连接文本
    ui->messageTextEdit->setText(connectTemp);          //显示已连接信息

    //设置文件按钮为可按
    ui->selectPushButton->setEnabled(true);             //设置选择文件按钮位可按
    ui->sendPushButton->setEnabled(true);               //设置发送文件按钮位可按

}

//定时器结束处理
void Widget::sendFileTimeoutHandler()
{
    sendFileTimer->stop();          //停止定时器
    char buf[4*1024] = {0};       //缓冲区
    qint64 bytesRead = file.read(buf, sizeof(buf)); // 读取实际字节数

    if(bytesRead>0)
    {
        qint64 bytesWritten = tcpSocket->write(buf, bytesRead); // 发送实际读取的字节
        if (bytesWritten == -1) {
            QMessageBox::warning(this, "错误", "发送失败");
            return;
        }
        senddFileSize += bytesWritten;

        // 未发送完则继续触发定时器
        if (senddFileSize < fileSize) {
            sendFileTimer->start(20);
        } else {
            QMessageBox::information(this, "完成", "文件发送完毕");
            file.close();
        }

    }
    else if(senddFileSize < fileSize)
    {
        QMessageBox::warning(this, "错误", "文件读取失败");
    }

}

//选择文件按钮
void Widget::on_selectPushButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this,"open","../");   //准备打开文件的路径
    //打开的文件路径不为空
    if(!filePath.isEmpty())
    {
        //获取文件信息
        QFileInfo fileInfo(filePath);       //文件信息

        fileName = fileInfo.fileName();     //文件名字
        fileSize = fileInfo.size();         //文件大小

        senddFileSize = 0;         //发送文件大小为0

        //以只读打开文件
        file.setFileName(filePath);     //准备打开的文件

        bool fileisOk = file.open(QIODevice::ReadOnly);         //以只读形式打开
        //打开文件失败
        if(fileisOk==false)
        {
            QMessageBox::warning(this,"打开文件","打开文件失败");     //显示打开文件失败消息框
        }

        //文件路径显示
        ui->messageTextEdit->setText(filePath);         //显示文件路径

        ui->selectPushButton->setEnabled(false);       //打开文件成功后选择文件按钮失效
        ui->sendPushButton->setEnabled(true);          //发送按钮文件生效
    }
    else
    {
        QMessageBox::warning(this,"打开文件失败","文件不能为空");      //显示打开文件错误消息框
    }

}

//发送文件按钮
void Widget::on_sendPushButton_clicked()
{
    //发送文件信息
    QString fileMes = QString("%1##%2\n").arg(fileName).arg(fileSize);       //发送文件的名字和大小

    qint64 fileLength = tcpSocket->write(fileMes.toUtf8().data());     //发送文件长度
    //发送文件成功
    if(fileLength > 0)
    {
        //发送文件的真正内容
        //距离太久会产生粘包问题
        //使用定时器解决粘包问题
        sendFileTimer->start(20);    //间隔20ms触发timeout定时器结束信号
    }
    else
    {
        QMessageBox::warning(this,"发送文件","发送文件失败");          //显示发送文件失败消息框

        file.close();           //关闭文件
        tcpSocket->disconnectFromHost();        //断开连接
        tcpSocket->close();       //关闭连接
    }
}
